package com.dtx.strategy;

import java.util.Random;

/**
 * ProStrategy类是另外一个具体策略,这个策略就需要"动点脑筋"了。
 * 虽然它与WinningStrategy一样,也是随机出手势,但是每种手势出现的概率会根据以前的猜拳结果而改变。
 * history字段是一个表,被用于根据过去的胜负进行概率计算。它是一个二维数组,每个数组下标的意思如下。
 *
 *  history[上一局出的手势][这一局所出的手势]
 *
 *  这个表达式的值越大,表示过去的胜率越高。下面稍微详细讲解下、
 *  假设我们上一局出的是石头。
 *
 *  history[0][0]   两局分别出石头,石头时胜了的次数
 *  history[0][1]   两局分别出石头,剪刀时胜了的次数
 *  history[0][2]   两局分别出石头,布时胜了的次数
 *
 * 那么,我们就可以根据history[0][0],history[0][1],history[0][2]这3个表达式的值从概率上计算出下一局出什么。
 * 简而言之,就是先计算3个表达式的值的和(getSum方法),然后再从0与这个和之间取一个随机数,并据此决定下一局应该出什么(nextHand方法)。
 *  例如,如果
 *  history[0][0] 是 3
 *  history[0][1] 是 5
 *  history[0][2] 是 7
 *
 * 那么,下一局出什么就会以石头,剪刀和布的比率为3:5:7来决定。然后在0至15(不含15,15是3+5+7的和)之间取一个随机数。
 *
 * 如果该随机数在0至3(不含3)之间,那么出石头
 * 如果该随机数在3至8(不含8)之间,那么出剪刀
 * 如果该随机数在8至15(不含15)之间,那么出布
 *
 * study方法会根据nextHand方法返回的手势的胜负结果来更新history字段中的值。
 *
 * 注意:      此策略的大前提是对方只有一种猜拳模式
 */
public class ProbStrategy implements Strategy{

    private Random random;

    private int preHandValue = 0;

    private int currentHandValue = 0;

    private int [][] history = {
            {1,1,1},
            {1,1,1},
            {1,1,1}
    };

    public ProbStrategy(int seed) {
        random = new Random(seed);
    }

    @Override
    public Hand nextHand() {

        int bet = random.nextInt(getSum(currentHandValue));

        int handValue = 0;

        if(bet < history[currentHandValue][0]){
            handValue = 0;
        }else if(bet < history[currentHandValue][0] + history[currentHandValue][1]){
            handValue = 1;
        }else {
            handValue = 2;
        }

        preHandValue = currentHandValue;

        currentHandValue = handValue;

        return Hand.getHand(handValue);
    }

    private int getSum(int hv){
        int sum = 0;
        for (int i = 0; i < 3; i++) {
            sum += history[hv][i];
        }
        return sum;
    }

    @Override
    public void study(boolean win) {
        if (win) {
            history[preHandValue][currentHandValue]++;
        }else {
            history[preHandValue][(currentHandValue + 1) % 3]++;
            history[preHandValue][(currentHandValue + 2) % 3]++;
        }
    }

}
